package cn.b.sky.common.controller;

import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.enums.DwzCallbackType;
import cn.b.sky.common.enums.DwzStatusCode;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.common.model.BatchJobReport;
import cn.b.sky.common.model.DWZResult;
import cn.b.sky.common.utils.AjaxUtil;
import cn.b.sky.common.utils.DatabaseUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;

@Slf4j
public abstract class BaseController {
    protected static final String NAVTABID = "navTabId";

    /**
     * <strong>Title : exp<br>
     * </strong> <strong>Description : </strong>全局异常处理<br>
     * <strong>Create on : 2016-4-26 下午2:42:23<br>
     * </strong>
     * <p>
     * 
     * @param response
     * @param response
     * @param ex
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    @ExceptionHandler
    public String exp(HttpServletResponse response, Exception ex) {
        String errorMsg = "";
        // 记录下日志
        log.error("{}", ex);
        if (ex instanceof ImeException) {
            // 抛出的是错误代码这里进行一次国际化处理
            errorMsg = getImeExceptionMessage(ex);
        } else {

            errorMsg = this.getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DWZ_CODE_ERROR_MESSAGE);
        }

        /* if (AjaxUtil.isAjax(request)) { */
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        String jsonObject = JSONObject.toJSONString(AjaxUtil.ajaxError(errorMsg, ex.getMessage()));
        PrintWriter out = null;
        try {

            out = response.getWriter();
            out.print(jsonObject);
            out.flush();
        } catch (IOException e) {

            log.error("{}", e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return null;
        /*
         * } else { request.setAttribute("template.message", errorMsg); request.setAttribute("errorMessage", ex.getMessage()); //
         * 根据不同错误转向不同页面 return "error/ime_exception"; }
         */
    }

    private String getDataIntegrityViolationExceptionMessage(Exception ex) {
        String errorMsg = ex.getMessage();
        if (DatabaseUtils.isConstraintsError(errorMsg)) {
            // 外键删除已存在提示
            errorMsg = this.getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DATABASE_OPERATION_FK);
        }
        return errorMsg;
    }

    private String getImeExceptionMessage(Exception ex) {

        ImeException exception = (ImeException) ex;
        return this.getImeViewMessageI18n(getCurrentLanguage(), exception.getErrorCode(), exception.getParameters());

    }

    /**
     * 
     * <strong>Title : getDWZJsonObject<br>
     * </strong> <strong>Description : </strong>@Dwz回调JsonObject的组装。@<br>
     * <strong>Create on : 2015年9月8日 上午11:19:12<br>
     * </strong>
     * <p>
     * 
     * @param statusCode dwz的回调状态 ，为枚举类DwzStatusCode的值。
     * @param message dwz的回调消息
     * @param navTabId dwz客户端的容器id为navTabId的容器会刷新
     * @param rel dwz的回调。当前navTab重新加载rel里面的接口
     * @param callbackType dwz客户端的回调类型，控制客户端的操作
     * @param forwardUrl 【选】配合callbackType进行操作
     * @param confirmMsg 【选】配合callbackType进行操作
     * @param data 自定义dwz数据请求的数据包
     * @return JSONObject
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult getDWZJsonObject(DwzStatusCode statusCode, String message, String navTabId, String rel,
            DwzCallbackType callbackType, String forwardUrl, String confirmMsg, Object data) {
        DWZResult dwzResult = null;

        if (null == statusCode) {// 回调状态
            log.error("Dwz 的状态码statusCode为null，异常状态。");
            return null;
        }
        if (null == callbackType) {// 回调状态
            callbackType = DwzCallbackType.EMPTY;
        }
        dwzResult = new DWZResult(statusCode.getValue(), message, navTabId, rel, callbackType.getValue(), forwardUrl,
                confirmMsg, data);
        return dwzResult;
    }

    /**
     * 
     * <strong>Title : navTabAjaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab ajax 请求成功的默认message自定义各项参数的回调 <br>
     * 匹配规则如下：（closeCurrent配合navTabId使用；forward配合forwardUrl使用； forwardConfirm配合confirmMsg【选】和forwardUrl和navTabId使用） <br>
     * {"statusCode":"301", "template.message":"会话超时"} <br>
     * {"statusCode":"300", "template.message":"操作失败"} <br>
     * {"statusCode":"200", "template.message":"操作成功", NAVTABID:"", "callbackType":"closeCurrent", "forwardUrl":""} <br>
     * {"statusCode":"200", "template.message":"操作成功", NAVTABID:"", "callbackType":"forwardConfirm", "confirmMsg【选】":"",
     * "forwardUrl":""} <br>
     * {"statusCode":"200", "template.message":"操作成功", "rel":"xxxId", "callbackType":"forward", "forwardUrl":""} <br>
     * 
     * @ <br>
     *   <strong>Create on : 2015年9月8日 下午1:49:51<br>
     *   </strong>
     *   <p>
     * 
     * @param navTabId dwz客户端的容器id为navTabId的容器会刷新
     * @param rel dwz客户端的回调。当前navTab重新加载rel里面的接口
     * @param callbackType dwz客户端的回调类型，控制客户端的操作
     * @param forwardUrl 【选】配合callbackType进行操作
     * @param confirmMsg 【选】配合callbackType进行操作
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult navTabAjaxDone(String navTabId, String rel, DwzCallbackType callbackType, String forwardUrl,
            String confirmMsg, Object data) {
        return navTabAjaxDone(getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DWZ_CODE_OK_MESSAGE), navTabId,
                rel, callbackType, forwardUrl, confirmMsg, data);
    }

    /**
     * 
     * <strong>Title : navTabAjaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab ajax 请求成功的自定义各项参数的回调@<br>
     * <strong>Create on : 2015年9月8日 下午1:51:52<br>
     * </strong>
     * <p>
     * 
     * @param message dwz客户端的回调消息
     * @param navTabId dwz客户端的容器id为navTabId的容器会刷新
     * @param rel dwz客户端的回调。当前navTab重新加载rel里面的接口
     * @param callbackType dwz客户端的回调类型，控制客户端的操作
     * @param forwardUrl 【选】配合callbackType进行操作
     * @param confirmMsg 【选】配合callbackType进行操作
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult navTabAjaxDone(String message, String navTabId, String rel, DwzCallbackType callbackType,
            String forwardUrl, String confirmMsg, Object data) {
        return getDWZJsonObject(DwzStatusCode.OK, message, navTabId, rel, callbackType, forwardUrl, confirmMsg, data);
    }

    /**
     * 
     * <strong>Title : dialogAjaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的dialog ajax 请求成功的默认message的自定义各项参数的回调 <br>
     * 匹配规则如下：（navTabId配合forwardUrl使用；rel单独使用） <br>
     * {"statusCode":"301", "template.message":"会话超时"} <br>
     * {"statusCode":"300", "template.message":"操作失败"} <br>
     * {"statusCode":"200", "template.message":"操作成功", NAVTABID:"", "forwardUrl":""} <br>
     * {"statusCode":"200", "template.message":"操作成功", "rel":"xxxId"} <br>
     * 
     * @ <strong>Create on : 2015年9月8日 下午2:28:27<br>
     *   </strong>
     *   <p>
     * 
     * @param navTabId dwz客户端的容器id为navTabId的容器会刷新
     * @param rel dwz客户端的回调。当前navTab重新加载rel里面的接口
     * @param forwardUrl 【选】配合callbackType进行操作
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult dialogAjaxDone(String navTabId, String rel, String forwardUrl, Object data) {
        return dialogAjaxDone(getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DWZ_CODE_OK_MESSAGE), navTabId,
                rel, forwardUrl, data);
    }

    /**
     * 
     * <strong>Title : dialogAjaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的dialog ajax 请求成功的自定义各项参数的回调@<br>
     * <strong>Create on : 2015年9月8日 下午2:29:41<br>
     * </strong>
     * <p>
     * 
     * @param message dwz客户端的回调消息
     * @param navTabId dwz客户端的容器id为navTabId的容器会刷新
     * @param rel dwz客户端的回调。当前navTab重新加载rel里面的接口
     * @param forwardUrl 【选】配合callbackType进行操作
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult dialogAjaxDone(String message, String navTabId, String rel, String forwardUrl, Object data) {
        return getDWZJsonObject(DwzStatusCode.OK, message, navTabId, rel, DwzCallbackType.CLOSECURRENT, forwardUrl,
                null, data);
    }

    /**
     * 
     * <strong>Title : ajaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab ajax 请求成功无参数的回调@<br>
     * <strong>Create on : 2015年9月8日 下午2:22:03<br>
     * </strong>
     * <p>
     * 
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult ajaxDone(Object data) {
        return ajaxDone(getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DWZ_CODE_OK_MESSAGE), data);
    }

    /**
     * 
     * <strong>Title : ajaxDone<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab ajax 请求成功自定义message参数的回调@<br>
     * <strong>Create on : 2015年9月8日 下午2:22:40<br>
     * </strong>
     * <p>
     * 
     * @param message
     * @param data 自定义dwz数据请求的数据包
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult ajaxDone(String message, Object data) {
        return getDWZJsonObject(DwzStatusCode.OK, message, null, null, DwzCallbackType.EMPTY, null, null, data);
    }

    /**
     * 
     * <strong>Title : navTabAjaxError<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab/dialog ajax 请求失败的默认回调@<br>
     * <strong>Create on : 2015年9月8日 下午1:45:52<br>
     * </strong>
     * <p>
     * 
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult navTabAjaxError() {
        return ajaxError(getImeViewMessageI18n(getCurrentLanguage(), SystemConstant.DWZ_CODE_ERROR_MESSAGE));
    }

    /**
     * 
     * <strong>Title : navTabAjaxError<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab/dialog ajax 请求失败的自定义message回调@<br>
     * <strong>Create on : 2015年9月8日 下午1:46:59<br>
     * </strong>
     * <p>
     * 
     * @param message
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult ajaxError(String message) {
        return getDWZJsonObject(DwzStatusCode.ERROR, message, null, null, DwzCallbackType.EMPTY, null, null, null);
    }

    /**
     * 
     * <strong>Title : navTabAjaxTimeout<br>
     * </strong> <strong>Description : </strong>@DWZ客户端的navTab/dialog ajax 请求超时的自定义message回调@<br>
     * <strong>Create on : 2015年9月8日 下午1:47:40<br>
     * </strong>
     * <p>
     * 
     * @param message
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult ajaxTimeout(String message) {
        return getDWZJsonObject(DwzStatusCode.TIMEOUT, message, null, null, DwzCallbackType.EMPTY, null, null, null);
    }

    /**
     * 
     * <strong>Title : getServletPath<br>
     * </strong> <strong>Description : </strong>获取系统绝对路径<br>
     * <strong>Create on : 2015-9-25 下午01:30:29<br>
     * </strong>
     * <p>
     * 
     * @param request
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public String getServletPath(HttpServletRequest request) {

        return request.getContextPath();
    }

    /**
     * 
     * <strong>Title : getForwardUrl<br>
     * </strong> <strong>Description : </strong>获取项目名和控制器接口名【/manage/service/serviceList】<br>
     * <strong>Create on : 2016-4-26 下午2:12:28<br>
     * </strong>
     * <p>
     * 
     * @param request
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public String getForwardUrl(HttpServletRequest request) {
        String requestUrl = request.getServletPath();
        String[] url = requestUrl.split("/");
        String forwardUrl = "";
        if (url.length > 1) {
            forwardUrl = request.getContextPath() + "/" + url[1];
        }
        return forwardUrl;
    }

    /**
     * <strong>Title : getCurrentLanguage<br>
     * </strong> <strong>Description : </strong>国际化的语言实现类实现<br>
     * <strong>Create on : 2016-4-26 下午2:23:55<br>
     * </strong>
     * <p>
     * 
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public abstract String getCurrentLanguage();

    /**
     * 
     * <strong>Title : getSiteCode<br>
     * </strong> <strong>Description : </strong>当前工厂<br>
     * <strong>Create on : 2016-6-15 下午5:47:48<br>
     * </strong>
     * <p>
     * 
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public abstract String getSiteCode();

    /**
     * 
     * <strong>Title : batchjobAjaxDone<br>
     * </strong> <strong>Description : </strong>批量删除返回方法<br>
     * <strong>Create on : 2015-12-21 下午6:07:32<br>
     * </strong>
     * <p>
     * 
     * @param request
     * @param reports
     * @return DWZResult
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult batchjobAjaxDone(HttpServletRequest request, List<BatchJobReport> reports) {
        return this.batchjobAjaxDone(request, DwzCallbackType.EMPTY, reports);
    }

    /**
     * 
     * <strong>Title : batchjobAjaxDone<br>
     * </strong> <strong>Description : </strong>重构下批量作业的返回方法，支持dialog批量操作<br>
     * <strong>Create on : 2016-4-6 下午6:48:08<br>
     * </strong>
     * <p>
     * 
     * @param request
     * @param callbackType
     * @param reports
     * @return DWZResult
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public DWZResult batchjobAjaxDone(HttpServletRequest request, DwzCallbackType callbackType,
            List<BatchJobReport> reports) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("title", this.getImeViewMessageI18n(this.getCurrentLanguage(), "detailReort.D"));
        map.put("data", setI18nMessage(reports));
        String jsonData = JSONObject.toJSONString(map);
        String forwardUrl = request.getContextPath() + "/manage/common/showReport";
        return getDWZJsonObject(DwzStatusCode.OK, null, null, null, callbackType, forwardUrl, null, jsonData);
    }

    /**
     * 抽离国际化
     */
    private Object setI18nMessage(List<BatchJobReport> reports) {
        for (BatchJobReport br : reports) {
            if (br.isSuccess()) {
                br.setResult(this.getImeViewMessageI18n(this.getCurrentLanguage(), "success.C"));
            } else {
                br.setResult(this.getImeViewMessageI18n(this.getCurrentLanguage(), "fail.C"));
            }
        }
        return reports;
    }

    /**
     * 
     * <strong>Title : getImeViewMessageI18n<br>
     * </strong> <strong>Description : </strong>获取国际化，code可以支持多个用“，”隔开， 但是此时的parameters不起作用<br>
     * <strong>Create on : 2016-4-15 上午10:33:07<br>
     * </strong>
     * <p>
     * 
     * @param lang
     * @param code
     * @param parameters
     * @return String
     * @throws @author lidapeng<br>
     * @version <strong>v1.0.0</strong><br>
     *          <br>
     *          <strong>修改历史:</strong><br>
     *          修改人 | 修改日期 | 修改描述<br>
     *          -------------------------------------------<br>
     *          <br>
     *          <br>
     */
    public abstract String getImeViewMessageI18n(String lang, String code, String... parameters);
}
